"""线程池的使用
使用标准库threading和multiprocessing模块可以实现多线程和多进程的任务，但是当项目达到一定的规模时，频繁的创建或销毁进程或线程，是非常耗资源的，这时候我们就要使用线程池或进程池，以空间换时间。

python标准库为我们提供了一个concurrent.futures的模块，它包括：ThreadPoolExecutor和ProcessPoolExecutor两个类，实现对threading和multiprocessing的进一步抽象，对编写线程池和进程池提供了直接的支持。

ThreadPoolExecutor和ProcessPoolExecutor创建线程池和进程池的类，我们把相应的任务（tasks）直接放到线程池或进程池中，不需要维护Queue来操行死锁的问题，线程池和进程池会自动帮我们调度。

future 可以理解为未来完成的操作，这是异步编程的基础，传统的编程模式下，如：queue.get的时候，等待结果返回之前会堵塞，而future的引入则会帮我们在等待的这段时间可以完成其他操作。

submit方法的使用： submit(fn, *args, * *kwargs):

安排可调用对象 fn 以 fn(*args, * *kwargs) 的形式执行，并返回 Future 对象来表示它的执行。"""
from concurrent.futures import ThreadPoolExecutor
import time
import requests


def thread_run(url):
    try:
        re = requests.get(url=url, timeout=30)
        re.raise_for_status()
        re.encoding = re.apparent_encoding
        return re.text
    except:
        return


if __name__ == "__main__":
    # 创建线程池实例对象
    executor = ThreadPoolExecutor(max_workers=2)

    # submit函数用来提交线程需要执行的任务到线程池中，并返回该任务的句柄（类似与文件，画图）（返回一个future实例），
    # 注意，submit()函数立即返回，不堵塞
    future1 = executor.submit(thread_run, "https://blog.csdn.net/weixin_41599977/article/details/92404112")
    future2 = executor.submit(thread_run, "https://blog.csdn.net/weixin_41599977/article/details/91048654")

    # submit函数返回的任务句柄可以使用done()方法判断该任务是否结束
    print(future1.done())

    # cancel函数可以取消提交的任务，但是如果任务已经在线程池中运行了，就取消不了了
    print(future2.cancel())

    time.sleep(4)
    print(future1.done())

    # result方法可以获取任务的返回值，这个方法是堵塞的(同步执行)
    print("the page 1 is {} bytes".format(len(future1.result())))
